/*
 * DocumentClass.hpp
 *
 *  Created on: 30.09.2012
 *      Author: dom
 */

#ifndef DOCUMENTCLASS_HPP_
#define DOCUMENTCLASS_HPP_

#include <hash_set>
#include <string>
#include <memory>

namespace mpei {

template<typename _T,
		template<class _Value, class _HashFcn = std::hash<_Value>,
				class _EqualKey = std::equal_to<_Value>,
				class _Alloc = std::allocator<_Value> > class _Container = __gnu_cxx::hash_set,
		typename _Str = std::string>
class DocumentClass {
	typedef typename _T::value_shared_ptr _value_shared_ptr;
public:
	typedef _T value_type;
	typedef std::shared_ptr<_T> value_shared_ptr;
	typedef std::shared_ptr<DocumentClass<_T, _Container> > shared_ptr;
	typedef _Container<value_shared_ptr> container;
	typedef typename container::iterator iterator;
	typedef std::map<std::string, double> token_map; //hardcore

	DocumentClass() {
	}

	DocumentClass(const _Str & name) :
			class_name(name) {
	}

	virtual ~DocumentClass() {
	}

	void insert(const value_shared_ptr document) {
		documents.insert(document);
		document->setDocumentClass(this);
	}

//	// if this variable create in stack!?
//	void insert(const _Tref document) {
//		documents.insert(&document);
//	}

	_Container<value_shared_ptr> get() {
		return this->documents;
	}

	//TODO
	value_shared_ptr getCentroid() {
		if (centroid.get() != nullptr) {
			return centroid;
		}
		size_t doc_size_ = documents.size();
		centroid = value_shared_ptr(new _T(class_name + "_centroid"));
		centroid->setDocumentClass(this);
		if(tokens.empty())
			getTokens();
		for (auto token_ : tokens) {
			centroid->insert(token_);
		}
		centroid->toCentroid(doc_size_);

//		for (auto token_ : all_tokens_) {
//			std::cout << token_->getFrequency() << std::endl;
//		}
		return centroid;
	}

	void setClassName(const _Str & src) {
		class_name = src;
	}

	_Str & getClassName() {
		return class_name;
	}

	std::vector<_value_shared_ptr> getTokens() {
		for (auto document_ : documents) {

			tokens.insert(tokens.end(), document_->get().begin(),
					document_->get().end());
		}
		return tokens;
	}

	token_map getTokensTf() {
		token_map map;
		if(tokens.empty())
			getTokens();
		for (auto token : tokens) {
			map[token->data()]++;
		}
		return map;
	}
protected:
	_Container<value_shared_ptr> documents;
	std::vector<_value_shared_ptr> tokens;
	_Str class_name;
	value_shared_ptr centroid;
};

}
// namespace mpei

#endif /* DOCUMENTCLASS_HPP_ */
